<template>
  <div class="asset-tags">
    <div ref="container" class="tag-container">
      <div
        v-for="(child, i) in tags"
        :key="i"
        class="tag main-tag"
        :class="{ hide: i >= showNum }"
      >
        <span @click="tagClick(child.tag)">{{ child.tag }}</span>
        <el-icon
          v-if="child.modifiable"
          class="tag-close"
          @click="delTag(child.tag, i)"
          ><Close
        /></el-icon>
      </div>

      <el-popover
        v-if="showNum < tags.length"
        placement="bottom"
        :append-to-body="false"
        trigger="hover"
      >
        <div class="tag-container pop-container">
          <div
            v-for="(pop_tag, pop_i) in tags.slice(showNum)"
            :key="`pop_${pop_i}`"
            class="tag"
          >
            <span>{{ pop_tag.tag }}</span>
            <el-icon
              v-if="pop_tag.modifiable"
              class="tag-close"
              @click="delTag(pop_tag.tag, pop_i)"
              ><Close
            /></el-icon>
          </div>
        </div>
        <template #reference>
          <div class="tag tag-num">
            <span>({{ tags.length - showNum }})</span>
          </div>
        </template>
      </el-popover>
      <div v-if="!disabled && tags.length < maxTagLength" class="new-container">
        <el-autocomplete
          v-if="inputVisible"
          ref="saveTagInput"
          v-model.trim="inputValue"
          class="new-tag-input"
          :popper-append-to-body="false"
          :fetch-suggestions="querySearch"
          :maxlength="maxTextLength"
          @blur="cancelInput"
          @input="changeInput"
          @select="selectInput"
          @keyup.enter="inputConfirm"
        >
          <template #suffix>
            <el-icon class="el-input__icon" @click="inputConfirm"
              ><Check
            /></el-icon>
          </template>
        </el-autocomplete>
        <div v-else class="new-tag" @click="showInput">+ 新增标签</div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import {
  defineProps,
  defineEmits,
  ref,
  watch,
  inject,
  ref as refDom,
  onMounted,
  nextTick,
  onBeforeUnmount,
} from 'vue';
import { useStore } from 'vuex';
import { ElMessage } from 'element-plus';
const aggregation = inject('aggregation', null);
const emit = defineEmits(['tagClick', 'updateTags', 'input']);
const store = useStore();
const props = defineProps({
  value: {
    type: Array, // 确保类型是 Array
    default: () => [],
  },
  disabled: {
    // 是否禁用
    type: Boolean,
    default: false,
  },
  maxTagLength: {
    // 最多输入多少个标签
    type: Number,
    default: 999,
  },
  maxTextLength: {
    // 标签最大输入文本数
    type: Number,
    default: 20,
  },
  colNum: {
    // 允许展示的行数 0 为不限制
    type: Number,
    default: 0,
  },
  id: {
    // 资产id
    type: String,
    default: '',
  },
  category: {
    type: String,
    default: '',
  },
  isBatch: {
    // 是否批量操作
    type: Boolean,
    default: false,
  },
});
const tags = ref<any>([]);
const queryTags = ref<any>([]);
const inputVisible = ref<Boolean>(false);
const inputValue = ref<String>('');
const showNum = ref<any>(99); // 显示的标签数
const timer = ref<any>(null);
const saveTagInput = ref<any>(null); // 用来保存对 input 元素的引用
// 监听 props.value 的变化
watch(
  () => props.value,
  (newVal) => {
    if (Array.isArray(newVal)) {
      tags.value = newVal;
    } else {
      tags.value = [];
    }
  },
  {
    immediate: true,
  },
);
watch(
  tags.value,
  () => {
    const container = ref(null);
    onMounted(() => {
      calculateShowNum(container.value);
    });
  },
  {
    immediate: true,
    deep: true,
  },
);

// 用来计算应该显示多少个标签的函数
const calculateShowNum = (container) => {
  if (!container) return;
  showNum.value = 99; // 初始值或根据计算后的值设置
  if (props.colNum === 0) return;

  nextTick(() => {
    let showNum = 0;
    const containerWidth = container.clientWidth;
    const children = Array.from(container.querySelectorAll('.main-tag'));
    let usedWidth = 0;
    let usedCol = 1;
    const allowWidth = children.length >= props.maxTagLength ? 50 : 200;

    for (let i = 0; i < children.length; i++) {
      const curWidth = (children[i] as any).offsetWidth + 8;
      if (usedWidth + curWidth < containerWidth) {
        if (usedCol < props.colNum) {
          showNum++;
          usedWidth += curWidth;
        } else {
          if (usedWidth + curWidth < containerWidth - allowWidth) {
            showNum++;
            usedWidth += curWidth;
          } else {
            break;
          }
        }
      } else {
        if (usedCol < props.colNum) {
          usedCol++;
          showNum++;
          usedWidth = curWidth;
        } else {
          break;
        }
      }
    }
    (showNum as any).value = showNum; // 更新响应式状态的 showNum
  });
};
// 在组件卸载前清除定时器
onBeforeUnmount(() => {
  clearTimeout(timer.value);
});

const tagClick = (val) => {
  emit('tagClick', val);
};
const showInput = () => {
  inputVisible.value = true;
  nextTick(() => {
    saveTagInput.value.focus();
  });
};

const updateValue = (v) => {
  emit('input', v);
};

const inputConfirm = async () => {
  const inputValues = inputValue.value;
  if (tags.value.some((el) => el.tag === inputValues)) {
    return ElMessage.error('输入标签已存在');
  }
  if (!inputValues) return;
  if (props.isBatch) {
    tags.value.push({
      tag: inputValue.value,
      modifiable: true,
    });
    inputVisible.value = false;
    inputValue.value = '';
    updateValue(tags.value);
    return;
  }
  
  const { code, data } = await store.dispatch('attack/appendTagsV2', {
    assets: [
      {
        assetId: props.id,
        category: props.category,
      },
    ],
    tags: [inputValues],
  });

  
  if (code === 0) {
    tags.value.push({
      tag: inputValues,
      modifiable: true,
    });
    inputVisible.value = false;
    inputValue.value = '';
    setTimeout(() => {
      emit('updateTags');
    }, 2000);
  }
};

const cancelInput = () => {
  setTimeout(() => {
    if (!inputValue.value) {
      inputVisible.value = false;
    }
  }, 222);
};
const changeInput = (v) => {
  inputValue.value = inputValue.value.replace(/,/g, '');
};
const selectInput = (item) => {
  inputValue.value = item.tag;
};
// 模糊匹配
const querySearch = async (queryString, cb) => {
  const { code, data } = await store.dispatch('attack/queryTagList', {
    tag: queryString,
    pageNumber: 1,
    pageSize: 1000,
  });
  if (code === 0) {
    const results = data.list;
    results.forEach((el) => {
      el.value = tags.value.map((item) => item.tag).includes(el.tag)
        ? el.tag + '（已添加）'
        : el.tag;
    });
    cb(results);
  }
};
// 删除标签
const delTag = async (tag, i) => {
  const tagss = tags.value.filter((el) => el.tag !== tag);
  if (props.isBatch) {
    tags.value = tagss;
    updateValue(tags.value);
    return;
  }
  const { code, data } = await store.dispatch('attack/deleteTags', {
    exposedCode: props.category,
    assetId: props.id,
    tag,
  });
  if (code === 0) {
    tags.value = tagss;
    setTimeout(() => {
      emit('updateTags');
    }, 2000);
  }
};
</script>
<style lang="scss" scoped>
.asset-tags {
  // display: flex;
  // background: #242731;
  .tag-container {
    // flex: 1;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    // width: 0;
    .tag {
      flex: 0 0 auto;
      display: flex;
      align-items: center;
      height: 26px;
      box-sizing: border-box;
      padding: 0 12px;
      margin-bottom: 12px;
      font-family: PingFang SC;
      font-size: 12px;
      font-weight: normal;
      letter-spacing: 0em;
      line-height: 12px;
      color: #3aceff;
      border: 0.5px solid rgba(58, 206, 255, 0.6);
      border-radius: 4px;
      background: rgba(58, 206, 255, 0.1);
      &:hover:not(.tag-num) {
        // padding: 0 6px;
        background: rgba(58, 206, 255, 0.3);
        .tag-close {
          display: inherit;
        }
      }
      &.tag-num {
        max-width: 50px;
        margin-right: 8px !important;
        &:hover {
          background: rgba(58, 206, 255, 0.3);
        }
      }
      &:not(:last-of-type) {
        margin-right: 8px;
      }
      > span {
        cursor: pointer;
      }
      .tag-close {
        width: 12px;
        margin-left: 4px;
        display: none;
        cursor: pointer;
      }
    }
  }
  .new-container {
    // margin-left: 8px;
    margin-bottom: 12px;
    line-height: 14px;
    flex: 0 0 auto;
    .new-tag {
      display: flex;
      align-items: center;
      height: 26px;
      box-sizing: border-box;
      padding: 0 10px;
      font-family: PingFang SC;
      font-size: 12px;
      font-weight: normal;
      letter-spacing: 0em;
      line-height: 12px;
      color: $-v-color-primary;
      background: rgba(58, 125, 255, 0.1);
      border: 0.5px dashed $-v-color-primary;
      border-radius: 4px;
      cursor: pointer;
      &:hover {
        box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.3);
      }
    }

    &::v-deep .el-input__wrapper {
      width: 150px;
      height: 26px;
      font-size: 12px;
      border-radius: 13px;
      background: transparent;
      // border: 1px solid $-v-color-primary;
      // color: #d2deeb;
    }
    &::v-deep .el-input__icon {
      line-height: 26px;
      // color: #d2deeb;
      cursor: pointer;
      &:hover {
        color: $-v-color-primary;
      }
    }
    // &::v-deep .el-autocomplete-suggestion {
    //   background: #1b1b1b;
    //   border: 1px solid #313441;
    //   box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.3);
    //   .el-scrollbar {
    //     background: #1b1b1b;
    //     color: #d2deeb;
    //     .el-autocomplete-suggestion__wrap {
    //       padding: 6px 0;
    //     }
    //     .el-scrollbar__view li {
    //       font-size: 12px;
    //       color: $-white;
    //       line-height: 22px;
    //       text-align: start;
    //       &:hover {
    //         // color: $-v-color-white;
    //         background: rgba(255, 255, 255, 0.1);
    //       }
    //       &.highlighted {
    //         color: $-v-color-white;
    //         background: rgba(255, 255, 255, 0.1);
    //       }
    //     }
    //   }
    //   .popper__arrow {
    //     border-bottom-color: #6d6d6d;
    //     border-top-color: #6d6d6d;
    //     &::after {
    //       border-bottom-color: #1b1b1b;
    //       border-top-color: #1b1b1b;
    //     }
    //   }
    // }
  }
  .pop-container {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    width: inherit;
    max-width: 360px;
    max-height: 200px;
    padding: 12px;
    overflow-y: auto;
    .tag {
      display: flex;
      align-items: center;
      height: 26px;
      box-sizing: border-box;
      padding: 0 12px;
      background: #24303d;
      margin-right: 0 !important;
      &:not(:first-of-type) {
        margin-left: 8px;
      }
      &:hover {
        background: #2b4f63 !important;
      }
    }
  }

  &::v-deep .el-popover {
    background: rgba(27, 27, 27, 0.7);
    border: 1px solid #313441;
    padding-bottom: 0;
    min-width: 50px;
    .popper__arrow {
      display: none;
    }
  }
}

.hide {
  display: none !important;
}
</style>
